<?php
/**
 * Prado Portal.
 *
 * @author Steen Rabol <steen.rabol@gmail.com>
 * @link http://www.pradoportal.dk/
 * @copyright Copyright &copy; 2006,2007,2008 Steen Rabol
 * @license http://www.pradoportal.dk
 * @version $Id: XMimeMail.php 289 2008-11-14 05:34:40Z steen.rabol@gmail.com $
 * @package Pradoportal.Common.XMimeMail
 *
 */

 /**
 * XMimeMail class file
 *
 * @author Philippe Gaultier <pgaultier@gmail.com>
 * @copyright Original code by Richard Heyes <richard.heyes@heyes-computing.net>
 * @version $Revision: 289 $  $Date: 2008-11-14 05:34:40 +0000 (Fri, 14 Nov 2008) $
 * @package XSystem.IO
 */

if( strncmp( PHP_OS, "WIN", 3 ) == 0 ) {
	// We are under windows, we must use getmxrr replacement function
	include_once(dirname(__FILE__).'/GetMXRR.php');
}


/**
 * XMimeMail class.
 *
 * XMimeMail implements a mime mailer.
 * Send mail through the php mail function.
 *
 * Usage HTML + Text replacement + inline image + attachment:
 * data needed
 * 	- $iso_mail_html : html content encoded in iso-8859-1
 * 	- $iso_mail_txt : text content (html replacement) encoded in iso-8859-1
 *  - $file_dir : directory where files should be searched (inline)(=".")
 *  - $inline_image : image to embed in the html mail (="image.jpg")
 *  - $attached_file :  file to attach to the mail (="file.pdf")
 *  - $mail_to_name
 *  - $mail_to_address
 *  - $mail_from_name
 *  - $mail_from_address
 *
 * <code>
 * $xMail = new XMimeMail();
 * $xMail->setCharset('iso-8859-1');
 * $xMail->embed($xMail->getFileContent("image.jpg"), "image.jpg");
 * // use embed if the image is not in the search path ($file_dir)
 * $xMail->attach($xMail->getFileContent("file.pdf"), "file.pdf");
 * $xMail->setHtmlBody($iso_mail_html, $iso_mail_txt, $file_dir);
 * 	$params['html_encoding'] = 'quoted-printable';
 * 	$params['text_encoding'] = 'quoted-printable';
 * 	$params['text_wrap'] = 998;
 * $xMail->prepare($params);
 * $xMail->send($mail_to_name, $mail_to_address, $mail_from_name, $mail_from_address, $iso_mail_subject);
 * unset($xMail);
 * </code>
 *
 * Usage Text only + attachment:
 * data needed
 * 	- $iso_mail_txt : text content encoded in iso-8859-1
 *  - $attached_file :  file to attach to the mail (="file.pdf")
 *  - $mail_to_name
 *  - $mail_to_address
 *  - $mail_from_name
 *  - $mail_from_address
 *
 * <code>
 * $xMail = new XMimeMail();
 * $xMail->setCharset('iso-8859-1');
 * $xMail->attach($xMail->getFileContent("file.pdf"), "file.pdf");
 * $xMail->setTextBody($iso_mail_txt);
 * 	$params['html_encoding'] = 'quoted-printable';
 * 	$params['text_encoding'] = 'quoted-printable';
 * 	$params['text_wrap'] = 998;
 * $xMail->prepare($params);
 * $xMail->send($mail_to_name, $mail_to_address, $mail_from_name, $mail_from_address, $iso_mail_subject);
 * unset($xMail);
 * </code>
 *
 * @author Philippe Gaultier <pgaultier@gmail.com>
 * @version $Revision: 289 $  $Date: 2008-11-14 05:34:40 +0000 (Fri, 14 Nov 2008) $
 * @package XSystem.IO
 * @since 3.0
 */
class XMimeMail{

	/**
	 * Mime Encoding
	 * @var string mime type
	 */
	private $_mime;
	/**
	 * HTML Body
	 * @var string html data
	 */
	private $_htmlBody;
	/**
	 * Text Body
	 * @var string text data
	 */
	private $_textBody;
	/**
	 * Check if the html part has been parsed
	 * @var boolean html check
	 */
	private $_doHtml;
	/**
	 * Multipart Body
	 * @var string multipart data
	 */
	private $_multipartData;
	/**
	 * Text Body when building an html email
	 * @var string text data
	 */
	private $_textHtmlBody;
	/**
	 * List of images
	 * @var array image list
	 */
	private $_embeddedImages = array();
	/**
	 * List of images types (extension, mimetype)
	 * @var array image mimetype list
	 */
	private $_imageMimeTypes = array(
									'gif'	=> 'image/gif',
									'jpg'	=> 'image/jpeg',
									'jpeg'	=> 'image/jpeg',
									'jpe'	=> 'image/jpeg',
									'bmp'	=> 'image/bmp',
									'png'	=> 'image/png',
									'tif'	=> 'image/tiff',
									'tiff'	=> 'image/tiff',
									'swf'	=> 'application/x-shockwave-flash'
								  );
	/**
	 * List of email parameters (encoding, ...)
	 * @var array parameters list
	 */
	private $_parameters = array(
									'html_encoding' => 'quoted-printable',
									'text_encoding' => '7bit',
									'text_wrap' => '7bit');
	/**
	 * List of headers
	 * @var array headers list
	 */
	private $_headers = array('MIME-Version: 1.0');
	/**
	 * List of different parts (mime type, data, ...)
	 * @var array parts list
	 */
	private $_parts = array();
	/**
	 * Charset used for the mail
	 * @var string charset
	 */
	private $_charset = 'iso-8859-1';
	/**
	 * Smtp object
	 * @var XSmtp smtp object
	 */
	private $_smtp=null;


   /**
    * MimeMail Class constructor. Sets the headers
	* if supplied.
    *
    * @param    mixed  $headers  Can be a string if there is only one line or an array for multiple lines
    * @access public
    */

	public function __construct($headers = ''){

		if(!defined('CRLF'))
			define('CRLF', "\n", TRUE);

		if($headers == '')
			return true;

		if(is_string($headers))
			$headers = explode(CRLF, trim($headers));

		for($i=0; $i<count($headers); $i++){
			if(is_array($headers[$i]))
				for($j=0; $j<count($headers[$i]); $j++)
					if($headers[$i][$j] != '')
						$this->_headers[] = $headers[$i][$j];

			if($headers[$i] != '')
				$this->_headers[] = $headers[$i];
		}
	}

	/**
	 * Accessor function to set the content charset.
     *
     * @param string $charset    Charset used for the message
     * @return boolean           true on success, false on error.
     * @access public
     */

	public function setCharset($charset = 'iso-8859-1'){

		if(is_string($charset)){
			$this->_charset = $charset;
			return true;
	    }
	    return false;
	}

	/**
	 * Accessor function to set the body text.
	 * Body text is used if it's not an html
	 * mail being sent.
     *
     * @param string $text           Text data for body generation
     * @return boolean               true on success, false on error.
     * @access public
     */
	public function setTextBody($text = ''){
		if(is_string($text)){
			$this->_textBody = $text;
			return true;
		}
		return false;
	}

	/**
	 * Adds a html part to the mail.
	 * Also replaces image names with
	 * content-id's.
	 *
	 * @param string $html       HTML content
	 * @param string $text       TEXT content
	 * @param string $images_dir Image directory (to auto embedd images)
     * @access public
     */

	public function setHtmlBody($html, $text, $images_dir = NULL){

		$this->_doHtml			= 1;
		$this->_htmlBody		= $html;
		$this->_textHtmlBody	= ($text == '') ? 'No text version was provided' : $text;

		if(isset($images_dir))
			$this->_findHtmlImages($images_dir);

		if(is_array($this->_embeddedImages) AND count($this->_embeddedImages) > 0){
			for($i=0; $i<count($this->_embeddedImages); $i++)
				$this->_htmlBody = str_replace($this->_embeddedImages[$i]['name'], 'cid:'.$this->_embeddedImages[$i]['cid'], $this->_htmlBody);
		}
	}

	/**
	 * Adds an image to the list of embedded
	 * images.
	 *
	 * @param string $file       file data {@link getFileContent()}
	 * @param string $name       file name
	 * @param string $c_type     mime type
     * @access public
     */

	public function embed($file, $name = '', $c_type='application/octet-stream'){
		$this->_embeddedImages[] = array(
										'body'   => $file,
										'name'   => $name,
										'c_type' => $c_type,
										'cid'    => md5(uniqid(time()))
									);
	}


	/**
	 * Adds a file to the list of attachments.
	 *
	 * @param string $file       file data {@link getFileContent()}
	 * @param string $name       file name
	 * @param string $c_type     mime type
     * @access public
     */

	public function attach($file, $name = '', $c_type='application/octet-stream'){
		$this->_parts[] = array(
										'body'   => $file,
										'name'   => $name,
										'c_type' => $c_type
							  );
	}

	/**
	 * Function to set a header. Shouldn't
	 * really be necessary as you could use
	 * the constructor and send functions,
	 * it's here nonetheless. Takes any number
	 * of arguments, which can be either
	 * strings or arrays full of strings.
     *
     * @param mixed $args           Any number of parameters (strings / array of strings)
     * @return boolean               true when finished
     * @access public
     */

	public function addHeader(){
		$args = func_get_args();
		for($i=0; $i<count($args); $i++){
			if(is_array($args[$i]))
				for($j=0; $j<count($args[$i]); $j++)
					if($args[$i][$j] != '')
						$this->_headers[] = $args[$i][$j];

			if($args[$i] != '')
				$this->_headers[] = $args[$i];
		}
		return true;
	}

	/**
	 * Open a file and return it's contact
	 * used in {@link embed()} or {@link attach()}
     *
     * @param string $filename   File to open
     * @return mixed             data on success, false on error.
     * @access public
     */

	public function getFileContent($filename){

		if($fp = fopen($filename, 'rb')){
			$return = fread($fp, filesize($filename));
			fclose($fp);
			return $return;
		} else
			return false;
	}

	/**
	 * Builds the multipart message from the
	 * list ($this->_parts).
	 *
	 * @param array $params     is an array of parameters that shape
	 *                          the building of the message. Currently
	 *                          supported are:
	 *                          $params['html_encoding'] - The type of
	 *                          encoding to use on html. Valid options are
	 *                          "7bit", "quoted-printable" or "base64"
	 *                          (all without quotes). 7bit is EXPRESSLY
	 *                          NOT RECOMMENDED. Default is quoted-printable
	 *                          $params['text_encoding'] - The type of
	 *                          encoding to use on plain text Valid options
	 *                          are "7bit", "quoted-printable" or "base64"
	 *                          (all without quotes). Default is 7bit
	 *                          $params['text_wrap']     - The character
	 *                          count at which to wrap 7bit encoded data.
	 *                          By default this is 998.
     * @access public
	 */
	public function prepare($params = array()){

		if(count($params) > 0)
			while(list($key, $value) = each($params))
				$this->_parameters[$key] = $value;

		$boundary = '=_'.md5(uniqid(time()));

		// Determine what needs building
		$do_html  = (isset($this->_doHtml) AND $this->_doHtml == 1) ? 1 : 0;
		$do_text  = (isset($this->_textBody)) ? 1 : 0;
		$do_parts = (count($this->_parts) > 0) ? 1 : 0;

		// Need to make this a multipart email?
		if($do_html OR $do_parts){
			$this->_headers[] = 'Content-Type: multipart/mixed;'.CRLF.chr(9).'boundary="'.$boundary.'"';
			$this->_multipartData = "This is a MIME encoded message.".CRLF.CRLF;

			// Build html parts
			if($do_html)
				$this->_buildHtml($boundary);

			// Build plain text part
			elseif($do_text)
				$this->_multipartData .= '--'.$boundary.CRLF.$this->_buildPart(array('body' => $this->_textBody, 'name' => '', 'c_type' => 'text/plain'));

		// No attachments or html, plain text
		}elseif($do_text AND !$do_parts){
			$this->_headers[] = 'Content-Type: text/plain;'.CRLF.chr(9).'charset="'.$this->_charset.'"';
			$this->_multipartData = $this->_textBody.CRLF.CRLF;
		}

		// Build all attachments
		if($do_parts)
			for($i=0; $i<count($this->_parts); $i++)
				$this->_multipartData.= '--'.$boundary.CRLF.$this->_buildPart($this->_parts[$i]);

		// Add closing boundary
		$this->_mime = ($do_parts OR $do_html) ? $this->_multipartData.'--'.$boundary.'--'.CRLF : $this->_multipartData;
	}

	/**
	 * Sends the mail.
	 *
	 * @param string $to_name     real name
	 * @param string $to_addr     email address
	 * @param string $from_name   real name
	 * @param string $from_addr   email address
	 * @param string $subject     subject text
	 * @param mixed $headers      additional headers (array / string)
     * @return boolean           true on success, false on error.
     * @access public
     */

	public function send($to_name, $to_addr, $from_name, $from_addr, $subject = '', $headers = ''){

        if(substr(PHP_OS, 0, 3) == "WIN")
        {
			$to = $to_addr;
			$from = $from_addr;
        }
		else
		{
			$to		= ($to_name != '')   ? '"' . $to_name . '" <' . $to_addr . '>' : $to_addr;
			$from	= ($from_name != '') ? '"'.$from_name.'" <'.$from_addr.'>' : $from_addr;
		}

		if(is_string($headers))
			$headers = explode(CRLF, trim($headers));

		for($i=0; $i<count($headers); $i++){
			if(is_array($headers[$i]))
				for($j=0; $j<count($headers[$i]); $j++)
					if($headers[$i][$j] != '')
						$xtra_headers[] = $headers[$i][$j];

			if($headers[$i] != '')
				$xtra_headers[] = $headers[$i];
		}
		if(!isset($xtra_headers))
			$xtra_headers = array();

		return mail($to, $subject, $this->_mime, 'From: '.$from.CRLF.implode(CRLF, $this->_headers).CRLF.implode(CRLF, $xtra_headers));
	}

	/**
	 * Open an smtp access to send e-mails
	 *
	 * @param string $smtpServer address of the SMTP server to relay
	 * @param string $localServer sender server address
	 * @param string $login Set to the user name if the server requires authetication
	 * @param string $password Set to the authentication password
	 * @param string $authMechanism
	 * @param string $realm Set to the authentication realm, usually the authentication user e-mail domain
	 * @param string $pop3AuthServer Set to the POP3 authentication host if your SMTP server requires prior POP3 authentication
	 * @param string $ntlmWorkstation
	 * @param string $directDelivery Set to 1 to deliver directly to the recepient SMTP server
	 * @param string $timeout Set to the number of seconds wait for a successful connection to the SMTP server
	 * @param string $dataTimeout Set to the number seconds wait for sending or retrieving data from the SMTP server.
	 *                            Set to 0 to use the same defined in the timeout variable
	 * @return boolean true if the object has been set up successfully false otherwise
	 */

	public function openStmp($smtpServer, $localServer='', $login='', $password='', $smtpPort=25, $authMechanism='', $realm='', $pop3AuthServer='',
							$ntlmWorkstation='', $directDelivery=0, $timeout=10, $dataTimeout=0)
	{
		//TODO: patch to be more prado like...
		if(!class_exists("XSasl"))
			require_once (dirname(__FILE__).'/XSasl.php');
		if(!class_exists("XSmtp"))
			require_once (dirname(__FILE__).'/XSmtp.php');
		if(class_exists("XSasl") && class_exists("XSmtp"))
		{
			if(is_null($this->_smtp)) {
				$this->_smtp = new XSmtp;
			}
			$this->_smtp->hostName = $smtpServer;
			$this->_smtp->localhost = $localServer;
			$this->_smtp->hostPort = $smtpPort;
			$this->_smtp->user = $login;
			$this->_smtp->password = $password;
			$this->_smtp->authenticationMechanism = $authMechanism;
			$this->_smtp->realm = $realm;
			$this->_smtp->workstation = $ntlmWorkstation;
			$this->_smtp->directDelivery = $directDelivery;
			$this->_smtp->timeout = $timeout;
			$this->_smtp->dataTimeout = $dataTimeout;
			return true;
		}
		else
			return false;

	}

	public function closeSmtp() {
		$this->_smtp=null;
	}

	/**
	 * Sends the mail.
	 *
	 * @param string $to_name     real name
	 * @param string $to_addr     email address
	 * @param string $from_name   real name
	 * @param string $from_addr   email address
	 * @param string $subject     subject text
	 * @param mixed $xtra_headers additional headers (array / string)
	 * @param boolean $fallback   use php mail function on smtp error
     * @return boolean            true on success, false on error.
     * @access public
     */

	public function sendSmtp($to_name, $to_addr, $from_name, $from_addr, $subject = '', $xtra_headers = '', $fallback = false){
		if(!is_null($this->_smtp))
		{
			$headers = $this->_headers;
			$to		= ($to_name != '')   ? '"'.$to_name.'" <'.$to_addr.'>' : $to_addr;
			$from	= ($from_name != '') ? '"'.$from_name.'" <'.$from_addr.'>' : $from_addr;

			if(is_string($xtra_headers))
				$xtra_headers = explode(CRLF, trim($xtra_headers));
			for($i=0; $i<count($xtra_headers); $i++){
				if(is_array($xtra_headers[$i]))
					for($j=0; $j<count($xtra_headers[$i]); $j++)
						if($xtra_headers[$i][$j] != '')
							$x_headers[] = $xtra_headers[$i][$j];

				if($xtra_headers[$i] != '')
					$x_headers[] = $xtra_headers[$i];
			}
			if(!isset($x_headers))
				$x_headers = array();
			$headers = array_merge($headers, $x_headers);
			$headers[] = "Subject: ".$subject;
			$headers[] = "To: ".$to;
			$headers[] = "From: ".$from;
			$mime = $this->_mime;

			if($this->_smtp->sendMessage($from_addr, array($to_addr), $headers, $mime)) {
				return true;
			} elseif($fallback) {
				if($this->send($to_name, $to_addr, $from_name, $from_addr, $subject, $xtra_headers)) {
					return true;
				} else
					return false;
			} else
				return false;
		} else
			return false;
	}


	/**
	 * Use this method to return the email
	 * in message/rfc822 format. Useful for
	 * adding an email to another email as
	 * an attachment.
	 *
	 * @param string $to_name     real name
	 * @param string $to_addr     email address
	 * @param string $from_name   real name
	 * @param string $from_addr   email address
	 * @param string $subject     subject text
	 * @param mixed $headers      additional headers (array / string)
     * @return string             email data.
     * @access public
     */

	public function rfc822($to_name, $to_addr, $from_name, $from_addr, $subject = '', $headers = ''){

		// Make up the date header as according to RFC822
		$date = 'Date: '.date('D, d M y H:i:s');

		$to   = ($to_name   != '') ? 'To: "'.$to_name.'" <'.$to_addr.'>' : 'To: '.$to_addr;
		$from = ($from_name != '') ? 'From: "'.$from_name.'" <'.$from_addr.'>' : 'From: '.$from_addr;

		if(is_string($subject))
			$subject = 'Subject: '.$subject;

		if(is_string($headers))
			$headers = explode(CRLF, trim($headers));

		for($i=0; $i<count($headers); $i++){
			if(is_array($headers[$i]))
				for($j=0; $j<count($headers[$i]); $j++)
					if($headers[$i][$j] != '')
						$xtra_headers[] = $headers[$i][$j];

			if($headers[$i] != '')
				$xtra_headers[] = $headers[$i];
		}

		if(!isset($xtra_headers))
			$xtra_headers = array();

		return $date.CRLF.$from.CRLF.$to.CRLF.$subject.CRLF.implode(CRLF, $this->_headers).CRLF.implode(CRLF, $xtra_headers).CRLF.CRLF.$this->_mime;
	}

	/**
	 * Function for extracting images from
	 * html source. This function will look
	 * through the html code supplied by {@link setHtmlBody()}
	 * and find any file that ends in one of the
	 * extensions defined in {@link _imageMimeTypes}.
	 * If the file exists it will read it in and
	 * embed it, (not an attachment).
	 * Function contributed by Dan Allen
	 *
	 * @param string $images_dir   Images directory
     * @access private
     */

	private function _findHtmlImages($images_dir) {

		// Build the list of image extensions
		while(list($key,) = each($this->_imageMimeTypes))
			$extensions[] = $key;
		$images = array();
		preg_match_all('/"([^"]+\.('.implode('|', $extensions).'))"/Ui', $this->_htmlBody, $images);

		for($i=0; $i<count($images[1]); $i++){
			if(file_exists($images_dir.$images[1][$i])){
				$html_images[] = $images[1][$i];
				$this->_htmlBody = str_replace($images[1][$i], basename($images[1][$i]), $this->_htmlBody);
			}
		}

		if(!empty($html_images)){

			// If duplicate images are embedded, they may show up as attachments, so remove them.
			$html_images = array_unique($html_images);
			sort($html_images);

			for($i=0; $i<count($html_images); $i++){
				if($image = $this->getFileContent($images_dir.$html_images[$i])){
					$content_type = $this->_imageMimeTypes[substr($html_images[$i], strrpos($html_images[$i], '.') + 1)];
					$this->embed($image, basename($html_images[$i]), $content_type);
				}
			}
		}
	}

	/**
	 * Encodes text to quoted printable standard.
	 * Function contributed by Allan Hansen
	 *
	 * @param string $input      text
	 * @param string $line_max   line length
     * @return string            encoded data
     * @access private
     */

	private function _qprint($input , $line_max = 76){

		$lines	= preg_split("/(?:\r\n|\r|\n)/", $input);
		$eol	= CRLF;
		$escape	= '=';
		$output	= '';

		while(list(, $line) = each($lines)){

			$linlen	 = strlen($line);
			$newline = '';

			for($i = 0; $i < $linlen; $i++){
				$char = substr($line, $i, 1);
				$dec  = ord($char);

				if(($dec == 32) AND ($i == ($linlen - 1)))				// convert space at eol only
					$char = '=20';

				elseif($dec == 9)
					;				// Do nothing if a tab.

				elseif(($dec == 61) OR ($dec < 32 ) OR ($dec > 126))
					$char = $escape.strtoupper(sprintf('%02s', dechex($dec)));

				if((strlen($newline) + strlen($char)) >= $line_max){	// CRLF is not counted
					$output  .= $newline.$escape.$eol;					// soft line break; " =\r\n" is okay
					$newline  = '';
				}
				$newline .= $char;
			} // end of for
			$output .= $newline.$eol;
		}
		return $output;
	}

	/**
	 * Function to return encoded text/html
	 * based upon the build params.
	 *
	 * @param string $data       data to encode
	 * @param string $encoding   encoding (7bit, quoted-printable, base64)
     * @return string            encoded data
     * @access private
     */


	private function _encodeData($data, $encoding){

		$return = '';

		switch($encoding){

			case '7bit':
				$return .=	'Content-Transfer-Encoding: 7bit'.CRLF.CRLF.
							chunk_split($data, $this->_parameters['text_wrap']);
				break;

			case 'quoted-printable':
				$return .=	'Content-Transfer-Encoding: quoted-printable'.CRLF.CRLF.
							$this->_qprint($data);
				break;

			case 'base64':
				$return .=	'Content-Transfer-Encoding: base64'.CRLF.CRLF.
							chunk_split(base64_encode($data));
				break;
		}

		return $return;
	}

	/**
	 * Builds html part of email.
	 *
	 * @param string $orig_boundary       boundary string
     * @access private
     */

	private function _buildHtml($orig_boundary){
		$sec_boundary = '=_'.md5(uniqid(time()));
		$thr_boundary = '=_'.md5(uniqid(time()));

		if(count($this->_embeddedImages) == 0){
			$this->_multipartData .= '--'.$orig_boundary.CRLF.
								'Content-Type: multipart/alternative;'.CRLF.chr(9).'boundary="'.$sec_boundary.'"'.CRLF.CRLF.
								'--'.$sec_boundary.CRLF.
								'Content-Type: text/plain; charset="'.$this->_charset.'"'.CRLF.
								$this->_encodeData($this->_textHtmlBody, $this->_parameters['text_encoding']).CRLF.
								'--'.$sec_boundary.CRLF.
								'Content-Type: text/html; charset="'.$this->_charset.'"'.CRLF.
								$this->_encodeData($this->_htmlBody, $this->_parameters['html_encoding']).CRLF.
								'--'.$sec_boundary.'--'.CRLF.CRLF;

		}else{

			$this->_multipartData .= '--'.$orig_boundary.CRLF.
								'Content-Type: multipart/related;'.CRLF.chr(9).'boundary="'.$sec_boundary.'"'.CRLF.CRLF.
								'--'.$sec_boundary.CRLF.
								'Content-Type: multipart/alternative;'.CRLF.chr(9).'boundary="'.$thr_boundary.'"'.CRLF.CRLF.
								'--'.$thr_boundary.CRLF.
								'Content-Type: text/plain; charset="'.$this->_charset.'"'.CRLF.
								$this->_encodeData($this->_textHtmlBody, $this->_parameters['text_encoding']).CRLF.
								'--'.$thr_boundary.CRLF.
								'Content-Type: text/html; charset="'.$this->_charset.'"'.CRLF.
								$this->_encodeData($this->_htmlBody, $this->_parameters['html_encoding']).CRLF.
								'--'.$thr_boundary.'--'.CRLF;

			for($i=0; $i<count($this->_embeddedImages); $i++){
				$this->_multipartData .= '--'.$sec_boundary.CRLF;
				$this->_buildHtmlImage($i);
			}

			$this->_multipartData .= '--'.$sec_boundary.'--'.CRLF;
		}
	}

	/**
	 * Builds an embedded image part of an
	 * html mail.
	 *
	 * @param integer $i       image offset
     * @access private
     */

	private function _buildHtmlImage($i){
		$this->_multipartData .= 'Content-Type: '.$this->_embeddedImages[$i]['c_type'];

		if($this->_embeddedImages[$i]['name'] != '')
			$this->_multipartData .= '; name="'.$this->_embeddedImages[$i]['name'].'"'.CRLF;
		else
			$this->_multipartData .= CRLF;

		$this->_multipartData .= 'Content-ID: <'.$this->_embeddedImages[$i]['cid'].'>'.CRLF;
		$this->_multipartData .= $this->_encodeData($this->_embeddedImages[$i]['body'], 'base64').CRLF;
	}

	/**
	 * Builds a single part of a multipart
	 * message.
	 *
	 * @param array $input       input part data
     * @return string            message part
     * @access private
     */

	private function _buildPart($input){
		$message_part  = '';
		$message_part .= 'Content-Type: '.$input['c_type'];
		if($input['name'] != '')
			$message_part .= ';'.CRLF.chr(9).'name="'.$input['name'].'"'.CRLF;
		else
			$message_part .= CRLF;

		// Determine content encoding.
		if($input['c_type'] == 'text/plain'){
			$message_part.= $this->_encodeData($input['body'], 'quoted-printable').CRLF;

		}elseif($input['c_type'] == 'message/rfc822'){
			$message_part .= 'Content-Disposition: attachment'.CRLF;
			$message_part .= $this->_encodeData($input['body'], '7bit').CRLF;

		}else{
			$message_part .= 'Content-Disposition: attachment; filename="'.$input['name'].'"'.CRLF;
			$message_part .= $this->_encodeData($input['body'], 'base64').CRLF;
		}

		return $message_part;
	}

	/**
	 * Accessor function to return the mime
	 * class variable. Purely for debug.
     *
     * @return string               Mime Part data or an empty string
     * @access private
     */
	protected function getMime(){
		if(!isset($this->_mime))
			$this->_mime = '';
		return $this->_mime;
	}

}
?>
